package com.fqgj.sentry.biz.decision.data;

import com.fqgj.base.services.redis.RedisClient;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.sentry.api.domain.*;
import com.fqgj.sentry.common.exception.BizException;
import com.fqgj.sentry.exception.ErrorCodeEnums;
import com.fqgj.sentry.manage.service.ApplicationService;
import com.fqgj.sentry.policy.client.ColumnService;
import com.fqgj.sentry.policy.client.PcTripleCallRecordService;
import com.fqgj.sentry.policy.engine.domain.Policy;
import com.fqgj.sentry.policy.engine.domain.PolicySet;
import com.fqgj.sentry.policy.engine.domain.Rule;
import com.fqgj.sentry.policy.engine.domain.WeightRange;
import com.fqgj.sentry.policy.engine.domain.enums.PolicyTypeEnum;
import com.fqgj.sentry.policy.engine.domain.enums.RuleComposeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by liupengpeng on 2017/8/17.
 */
@Service
public class DecisionResultAnalysis {
    @Autowired
    private RedisClient redisClient;
    @Autowired
    private ColumnService columnService;
    @Autowired
    private ApplicationService applicationService;
    @Autowired
    private PcTripleCallRecordService tripleCallRecordService;

    public static final String keyFormat = "{policySetFlowNo}_{apiName}";
    public static final String funKeyFormat = "{policySetFlowNo}_{functionCode}";

    public RiskApiResult getRiskResult(String merchantCode, String flowNo, List<PolicySet> policySetList) throws Exception {
        RiskApiResult riskResult = new RiskApiResult();
        riskResult.setCode("0");
        riskResult.setFlowNo(flowNo);

        List<ExecutorResult> executorResultList = new ArrayList<>();
        for (PolicySet policySet : policySetList) {
            riskResult.setPolicySetId(policySet.getPolicySetId());

            ExecutorResult executorResult = new ExecutorResult();
            executorResult.setPolicyList(getPolicy(policySet));
            executorResult.setExecutorId(policySet.getExecutorId())
                    .setExecutorType(policySet.getExecutorType())
                    .setEventId(policySet.getEventId()).setVersion(policySet.getVersion())
                    .setDecisionResult(new DecisionResult(
                            policySet.getPolicySetResult().getDecision().getDecisionName(),
                            policySet.getPolicySetResult().getDecision().getDecisionType(),
                            policySet.getPolicySetResult().getDecision().getPriority()
                    ));

            executorResultList.add(executorResult);
            if (policySet.getExecutorType() != null && policySet.getExecutorType() == 1) {
                riskResult.setVerifyResult(executorResult);
            } else {
                riskResult.setFinalResult(executorResult);
            }

        }
        return riskResult;
    }

    private List<ApiPolicy> getPolicy(PolicySet policySet) {
        if (CollectionUtils.isEmpty(policySet.getPolicySet())) {
            throw new BizException(ErrorCodeEnums.server_error);
        }
        List<ApiPolicy> apiPolicyArrayList = new ArrayList<>();
        for (Policy policy : policySet.getPolicySet()) {
            ApiPolicy apiPolicy = new ApiPolicy();
            apiPolicy.setPolicyId(policy.getPolicyId());
            apiPolicy.setStrategyName(policy.getPolicyName());
            apiPolicy.setPolicyType(policy.getPolicyType().ordinal() + 1);

            //公用条件是否命中
            apiPolicy.setHitCommonRule(true);
            Rule commonRule = policy.getCommonRule();
            if (commonRule != null) {
                if (!commonRule.getRuleResult().getHit()) {
                    apiPolicy.setHitCommonRule(false);
                    apiPolicyArrayList.add(apiPolicy);
                    continue;
                }
            }

            //如果是评分卡
            if (policy.getPolicyType().equals(PolicyTypeEnum.SCORE)) {
                ScoreCard scoreCard = new ScoreCard()
                        .setInitScore(Double.parseDouble(policy.getInitalScoreVariable().getValue().toString()))
                        .setFinalScore(policy.getPolicyResult().getSumScore())
                        .setColumnName(policy.getInitalScoreVariable().getName());
                apiPolicy.setScoreCard(scoreCard);
                apiPolicy.setHitRules(getScoreCardRules(policy));

            } else if (policy.getPolicyType().equals(PolicyTypeEnum.DECIDE)) { //如果是规则组

                apiPolicy.setDecisionResult(new DecisionResult(
                        policy.getPolicyResult().getPolicyDecision().getDecisionName(),
                        policy.getPolicyResult().getPolicyDecision().getDecisionType(),
                        policy.getPolicyResult().getPolicyDecision().getPriority()
                ));
                apiPolicy.setPolicyMode(policy.getRuleCompose().name());
                if (policy.getRuleCompose().equals(RuleComposeEnum.WEIGHT)) {//权重模式
                    WeightResult weightResult = new WeightResult();
                    weightResult.setScore(policy.getPolicyResult().getSumWeightScore().intValue())
                            .setWeightRangeResults(getWeightRangeResult(policy));
                    apiPolicy.setWeightResult(weightResult);
                }
                apiPolicy.setHitRules(getDecideHitRules(policy));
            }
            apiPolicyArrayList.add(apiPolicy);
        }
        return apiPolicyArrayList;
    }

    private List<HitRule> getScoreCardRules(com.fqgj.sentry.policy.engine.domain.Policy policy) {
        if (CollectionUtils.isEmpty(policy.getRuleList())) {
            throw new BizException(ErrorCodeEnums.server_error);
        }
        List<HitRule> hitRulesList = new ArrayList<>();
        for (Rule rule : policy.getRuleList()) {
            if (rule.getRuleResult().getHit()) {
                HitRule hitRule = new HitRule();
                hitRule.setRuleId(rule.getRuleId())
                        .setRuleName(rule.getRuleName())
                        .setCardScore(rule.getRuleResult().getScore());
                hitRulesList.add(hitRule);
            }

        }
        return hitRulesList;
    }

    private List<WeightRangeResult> getWeightRangeResult(Policy policy) {
        if (CollectionUtils.isEmpty(policy.getWeightRange())) {
            throw new BizException(ErrorCodeEnums.server_error);
        }
        List<WeightRangeResult> weightRangeResultList = new ArrayList<>();
        for (WeightRange weightRange : policy.getWeightRange()) {
            WeightRangeResult weightRangeResult = new WeightRangeResult();
            weightRangeResult.setDecision(weightRange.getDecision().getDecisionName())
                    .setDecisionType(weightRange.getDecision().getDecisionType())
                    .setPriority(weightRange.getDecision().getPriority())
                    .setStart(weightRange.getStart()).setEnd(weightRange.getEnd());
            weightRangeResultList.add(weightRangeResult);
        }
        return weightRangeResultList;
    }

    private List<HitRule> getDecideHitRules(com.fqgj.sentry.policy.engine.domain.Policy policy) {
        if (CollectionUtils.isEmpty(policy.getRuleList())) {
            throw new BizException(ErrorCodeEnums.server_error);
        }
        List<HitRule> hitRulesList = new ArrayList<>();
        if (policy.getRuleCompose().equals(RuleComposeEnum.FIRST)) {//如果是首次匹配
            for (Rule rule : policy.getRuleList()) {
                if (rule.getRuleResult().getHit()) {
                    HitRule hitRule = new HitRule();
                    hitRule.setRuleId(rule.getRuleId())
                            .setRuleName(rule.getRuleName())
                            .setDecision(rule.getRuleResult().getDecision().getDecisionName())
                            .setDecisionType(rule.getRuleResult().getDecision().getDecisionType())
                            .setPriority(rule.getRuleResult().getDecision().getPriority());

                    hitRulesList.add(hitRule);
                    break;
                }
            }
        } else if (policy.getRuleCompose().equals(RuleComposeEnum.WORST)) {//如果是最坏匹配
            for (Rule rule : policy.getRuleList()) {
                if (rule.getRuleResult().getHit()) {
                    HitRule hitRule = new HitRule();
                    hitRule.setRuleId(rule.getRuleId())
                            .setRuleName(rule.getRuleName())
                            .setDecision(rule.getRuleResult().getDecision().getDecisionName())
                            .setDecisionType(rule.getRuleResult().getDecision().getDecisionType())
                            .setPriority(rule.getRuleResult().getDecision().getPriority());

                    hitRulesList.add(hitRule);
                }
            }
        } else if (policy.getRuleCompose().equals(RuleComposeEnum.WEIGHT)) { //如果是权重匹配
            for (Rule rule : policy.getRuleList()) {
                if (rule.getRuleResult().getHit()) {
                    HitRule hitRule = new HitRule();
                    Double weightScore = rule.getRuleResult().getWeightScore();
                    hitRule.setRuleId(rule.getRuleId())
                            .setRuleName(rule.getRuleName())
                            .setWeightScore(weightScore.intValue());
                    hitRulesList.add(hitRule);
                }
            }
        }
        return hitRulesList;
    }

}
